package storage

import (
	"context"
	"fmt"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
	"go-caipu/pkg/services/storage/models"
	"io"
	"log"
	"path"
	"time"
)

type AliyunOSS struct {
	client *oss.Client
	config models.StorageConfig
}

func init() {
	Register(models.StorageAliYun, NewAliyunOSS)
}
func NewAliyunOSS() Storage {
	return &AliyunOSS{}
}

func (a *AliyunOSS) Init(config models.StorageConfig) error {
	// 构建凭证提供者
	credential := credentials.NewStaticCredentialsProvider(
		config.AccessKey,
		config.SecretKey,
		"",
	)
	cfg := oss.LoadDefaultConfig().WithCredentialsProvider(
		credential).WithEndpoint(config.Endpoint).WithRegion(config.Region)
	a.config = config
	//构建阿里云oss客户端
	a.client = oss.NewClient(cfg)

	//测试连接
	//ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	//defer cancel()

	//检查bucket是否存在
	return nil
}
func (a *AliyunOSS) Upload(ctx context.Context, reader io.Reader, storage *models.FileStorage) (*models.FileStorage, error) {
	//获取bucket客户端
	result, err := a.client.PutObject(ctx, &oss.PutObjectRequest{
		Bucket: oss.Ptr(a.config.BucketName),
		Key:    oss.Ptr(path.Join(storage.StoragePath, storage.FileKey)),
		Body:   reader,
	})
	if err != nil {
		return nil, err
	}
	fmt.Printf("put object result:%#v\n", result)
	return storage, nil
}

func (a *AliyunOSS) Download(ctx context.Context, staticPath, fileKey string) (io.ReadCloser, error) {

	request := &oss.GetObjectRequest{
		Bucket: oss.Ptr(a.config.BucketName),
		Key:    oss.Ptr(path.Join(staticPath, fileKey)),
	}
	result, err := a.client.GetObject(context.TODO(), request)
	if err != nil {
		log.Fatalf("failed to get object %v", err)
	}
	//defer result.Body.Close()
	log.Printf("get object result:%#v\n", result)
	//data, _ := io.ReadAll(result.Body)
	//log.Printf("body:%s\n", data)
	return result.Body, nil
}

func (a *AliyunOSS) Delete(ctx context.Context, storagePath, fileKey string) error {
	//TODO implement me
	_, err := a.client.DeleteObject(ctx, &oss.DeleteObjectRequest{
		Bucket: oss.Ptr(a.config.BucketName),
		Key:    oss.Ptr(path.Join(storagePath, fileKey)),
	})
	if err != nil {
		return err
	}
	return nil
}

func (a *AliyunOSS) GetFileURL(ctx context.Context, storagePath, fileKey string) (string, error) {
	//1.
	result, err := a.client.GetObject(ctx, &oss.GetObjectRequest{
		Bucket: oss.Ptr(a.config.BucketName),
		Key:    oss.Ptr(path.Join(storagePath, fileKey)),
	})
	if err != nil {
		return "", err
	}
	// 2. 配置签名选项 (可选)
	// 设置 URL 有效期，例如 15 分钟
	expireTime := time.Now().Add(15 * time.Minute)
	// 3. 生成预签名 URL
	presignResult, err := a.client.Presign(context.Background(), result, func(options *oss.PresignOptions) {
		options.Expiration = expireTime
	},
	)
	if err != nil {
		return "", err
	}
	// 4. 输出签名 URL
	fmt.Printf("Pre-signed URL for download: %s\n", presignResult.URL)
	// 通常直接使用 presignResult.URL 即可
	// presignResult.SignedHeader 是签名时包含的头信息，对于下载 URL 通常不需要
	return presignResult.URL, nil
}
